package helper.scxml.scxml2.t0.case3_factoryLines

import helper.base.BaseTypeHelper.toIntRange
import helper.base.debug.DebugHelper.DebuggerList.Companion.makeDebuggerList
import helper.base.debug.DebugRes.d_FL_learning
import helper.base.debug.DebugRes.d_ZoneLearningTest_t2t1
import helper.base.debug.DebugRes.d_t1t1Calculate
import helper.base.debug.DebugRes.d_t2t2_while
import helper.base.debug.DebugRes.d_t_2023_0828_143709_
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLEnvHelper.CalObj.D5DFun.Companion.getD5DFun
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLEnvHelper.CalObj.aD5DFun2
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLEnvHelper.FLEnv.Companion.makeFLEnv
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLEnvHelper.FLT3StrategyEx.Companion.makeFLT3StrategyEx
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLEnvHelper.StrategyObj.ER.aB2D2FLStrategy
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLEnvHelper.StrategyObj.ER.makeUniformFLStrategy
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLEnvHelper.TimeAndCalObj.TimeAndD5DFunClass
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLEnvHelper.TimeAndCalObj.TimeAndD5DFunClass.Companion.makeTimeAndD5DFunClass
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLLearningHelperKt.FLLearningHelper.Companion.aGetTotalScoreFun
import helper.scxml.scxml2.zone.t2.case3_factoryLines.FLLearningHelperKt.FLLearningHelper.Companion.makeFLLearningHelper
import helper.scxml.scxml2.zone.t2.ZoneLearningHelper.GetDFun.Companion.aGetDistanceToCovarianceMatrix
import helper.scxml.scxml2.zone.t2.ZoneLearningHelper.GetDFun.Companion.aGetDistanceToMean
import org.junit.Test

internal class FLLearningTask {
    val tempTimeObj20v1 = makeTimeAndD5DFunClass(
        20,
        getD5DFun { t, aA1C1, aB1C2, aA2D1, aB2D2 ->
            200.0 - (10 * aA1C1 + 10 * aB1C2 + 10 * aA2D1 + 20 * aB2D2)
        },
    )

    val tempTimeObj40v1 = makeTimeAndD5DFunClass(
        40,
        getD5DFun { t, aA1C1, aB1C2, aA2D1, aB2D2 ->
            400.0 - (10 * aA1C1 + 10 * aB1C2 + 10 * aA2D1 + 20 * aB2D2)
        },
    )

    val tempTimeObj60v1 = makeTimeAndD5DFunClass(
        60,
        getD5DFun { t, aA1C1, aB1C2, aA2D1, aB2D2 ->
            600.0 - (10 * aA1C1 + 10 * aB1C2 + 10 * aA2D1 + 20 * aB2D2)
        },
    )

    val tempTimeObj100v1 = makeTimeAndD5DFunClass(
        100,
        getD5DFun { t, aA1C1, aB1C2, aA2D1, aB2D2 ->
            1000.0 - (10 * aA1C1 + 10 * aB1C2 + 10 * aA2D1 + 20 * aB2D2)
        },
    )

    fun aGetUStrategyScoreFun(
        timeCalObj: TimeAndD5DFunClass,
        intRange: IntRange = 0.toIntRange(),
    ): Double {
        val env = makeFLEnv(timeCalObj.time)
        val cal = env.aT0Calculate(
            makeUniformFLStrategy(
                intRange,
            ),
            repeatTimes = 10000,
        )
        println(cal)
        val totalScore = aGetTotalScoreFun(timeCalObj.aFun, cal)
        println("bestTotalScore=${totalScore}")
        return totalScore
    }

    @Test
    fun test_aGetUStrategyScoreFun() {
        val timeCalObj = tempTimeObj100v1
        aGetUStrategyScoreFun(timeCalObj)
    }

    fun aGetBestStrategyScoreFun(
        timeCalObj: TimeAndD5DFunClass,
    ): Double {
        val env = makeFLEnv(timeCalObj.time)
        val cal = env.aT0Calculate(aB2D2FLStrategy, repeatTimes = 1)
        println(cal)
        val totalScore = aGetTotalScoreFun(timeCalObj.aFun, cal)
        println("bestTotalScore=${totalScore}")
        return totalScore
    }

    @Test
    fun test_aGetBestStrategyScoreFun() {
        val timeCalObj = tempTimeObj60v1
        aGetBestStrategyScoreFun(timeCalObj)
    }

    @Test
    fun t2t1_t1ByLearningMakeStrategy() {
        val timeCalObj = tempTimeObj100v1
        val t2ArgUnit = makeFLLearningHelper(
            maxRuns_repeatNum = 100,
            maxGood_repeatNum = 20,
            maxBest_heapSize = 40,
            maxNoBetter = 5,
            maxIterations = 1000,
            maxResets = 200,
            getDFun = aGetDistanceToMean,
            clearHeapP = 1.0,
            ifToTxt = true,
            doDoubleMatrixFun = {
                this
            },
            aDsDFun = timeCalObj.aFun,
            timeNeedEnd = timeCalObj.time,
        )
        val intRange = 0..20
        t2ArgUnit.aT1ByLearningMakeStrategy(
            aFLT3StrategyEx = makeFLT3StrategyEx(intRange),
            getUStrategyScoreFun = {
                aGetUStrategyScoreFun(timeCalObj, intRange)
            },
            getBestStrategyScoreFun = {
                aGetBestStrategyScoreFun(timeCalObj)
            },
            debuggerList = makeDebuggerList(
                d_t1t1Calculate,
                d_ZoneLearningTest_t2t1,
                d_FL_learning,
            ),
        )
    }

    @Test
    fun t2t2_t1ByLearningMakeStrategy() {
        val timeCalObj = tempTimeObj100v1
        val t2ArgUnit = makeFLLearningHelper(
            maxRuns_repeatNum = 100,
            maxGood_repeatNum = 20,
            maxBest_heapSize = 40,
            maxNoBetter = 5,
            maxIterations = 1000,
            maxResets = 20,
            getDFun = aGetDistanceToCovarianceMatrix,
            clearHeapP = 1.0,
            ifToTxt = true,
            doDoubleMatrixFun = {
                for (i in 0 until this.rows) {
                    this[i, i] += 0.01
                }
                this
            },
            aDsDFun = timeCalObj.aFun,
            timeNeedEnd = timeCalObj.time,
        )
        val intRange = 0..20
        t2ArgUnit.aT1ByLearningMakeStrategy(
            aFLT3StrategyEx = makeFLT3StrategyEx(intRange),
            getUStrategyScoreFun = {
                aGetUStrategyScoreFun(timeCalObj, intRange)
            },
            getBestStrategyScoreFun = {
                aGetBestStrategyScoreFun(timeCalObj)
            },
            debuggerList = makeDebuggerList(
                d_t1t1Calculate,
                d_ZoneLearningTest_t2t1,
                d_t_2023_0828_143709_,
                d_FL_learning,
                d_t2t2_while,
            ),
        )
    }

    @Test
    fun repeat_t2t1_t1ByLearningMakeStrategy() {
        val t2ArgUnit = makeFLLearningHelper(
            maxRuns_repeatNum = 200,
            maxGood_repeatNum = 10,
            maxBest_heapSize = 200,
            maxNoBetter = 10,
            maxIterations = 200,
            getDFun = aGetDistanceToMean,
            clearHeapP = 1.0,
            ifToTxt = true,
            doDoubleMatrixFun = {
                this
            },
            aDsDFun = aD5DFun2,
            timeNeedEnd = 20,
        )
        t2ArgUnit.repeatT1ByLearningMakeStrategy(
            repeatTimes = 10,
            debuggerList = makeDebuggerList(
                d_t1t1Calculate,
                d_ZoneLearningTest_t2t1,
                d_FL_learning,
            ),
        )
    }

    @Test
    fun repeat_t2t2_t1ByLearningMakeStrategy() {
        val t2ArgUnit = makeFLLearningHelper(
            maxRuns_repeatNum = 200,
            maxGood_repeatNum = 10,
            maxBest_heapSize = 200,
            maxNoBetter = 10,
            maxIterations = 200,
            getDFun = aGetDistanceToCovarianceMatrix,
            clearHeapP = 1.0,
            ifToTxt = true,
            doDoubleMatrixFun = {
                for (i in 0 until this.rows) {
                    this[i, i] += 0.01
                }
                this
            },
            aDsDFun = aD5DFun2,
            timeNeedEnd = 20,
        )
        t2ArgUnit.repeatT1ByLearningMakeStrategy(
            repeatTimes = 10,
            debuggerList = makeDebuggerList(
                d_t1t1Calculate,
                d_ZoneLearningTest_t2t1,
                d_t_2023_0828_143709_,
                d_FL_learning,
                d_t2t2_while,
            ),
        )
    }
}